// Path MTU Discovery

use std::time::{Duration, Instant};

const MIN_MTU: usize = 1280; // IPv6 minimum
const MAX_MTU: usize = 1500; // Ethernet MTU
const PROBE_INTERVAL: Duration = Duration::from_secs(30);

pub struct PmtudManager {
    current_mtu: usize,
    max_mtu: usize,
    last_probe: Instant,
    probe_size: usize,
}

impl PmtudManager {
    pub fn new() -> Self {
        Self {
            current_mtu: MIN_MTU,
            max_mtu: MAX_MTU,
            last_probe: Instant::now(),
            probe_size: MIN_MTU,
        }
    }

    pub fn current_mtu(&self) -> usize {
        self.current_mtu
    }

    pub fn should_probe(&self) -> bool {
        self.last_probe.elapsed() >= PROBE_INTERVAL && self.current_mtu < self.max_mtu
    }

    pub fn get_probe_size(&mut self) -> usize {
        self.probe_size = (self.current_mtu + self.max_mtu) / 2;
        self.last_probe = Instant::now();
        self.probe_size
    }

    pub fn on_probe_success(&mut self, size: usize) {
        if size > self.current_mtu {
            self.current_mtu = size;
        }
    }

    pub fn on_probe_failure(&mut self, size: usize) {
        if size < self.max_mtu {
            self.max_mtu = size - 1;
        }
    }
}

impl Default for PmtudManager {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_pmtud() {
        let mut pmtud = PmtudManager::new();
        assert_eq!(pmtud.current_mtu(), MIN_MTU);
        
        pmtud.on_probe_success(1400);
        assert_eq!(pmtud.current_mtu(), 1400);
    }
}
